//配置的变量，挂载在指定的全局变量中
class SystemEnv {
  constructor() {
    //在执行setNacosEnv方法后会覆盖
    this.nacos = env;
  }

  //是不是从本地文件夹打开的
  isLocalFileMode() {
    return (
      window.location.protocol === "file:" ||
      window.location.href.indexOf("src/main/resources/") > -1
    );
  }

  //是不是从本地部署的UI项目访问的
  isLocalHostMode() {
    return (
      window.location.hostname === "localhost" ||
      window.location.hostname === "127.0.0.1"
    );
  }

  //获取是否本地调试模式
  isLocalDebugMode() {
    return this.isLocalFileMode() || this.isLocalHostMode(); //true代表本地调试
  }

  //检查token，如果无效则到登录界面
  checkToken() {
    let token = localStorage.getItem("access_token");
    //token是否有效
    let tokenOk = token != undefined;
    if (tokenOk) {
      //有token还得看有效期是否过了
      if (self !== top) {
        // 嵌入 agcloud 情况下，有token就行
      } else {
        // 本地调试下,localDebugLogin/index.html调试登录界面会设置超时时间
        let lsTokenExpireTime = localStorage.getItem("token_expire_time");
        if (lsTokenExpireTime && new Date().getTime() > lsTokenExpireTime) {
          //超时了
          localStorage.removeItem("access_token");
          localStorage.removeItem("token_expire_time");
          tokenOk = false;
        }
      }
    }
    if (!tokenOk) {
      //如果token无效要去登录界面
      // frame 仿制页面, 本地登录页面免登录;
      let documentTitle = document.title;
      if (
        documentTitle === "奥格城市信息模型基础平台" ||
        documentTitle === "Local login"
      )
        return;
      let curPath = window.location.href;
      let baseUrl = new Base64().encode(curPath);
      // 本地调试时进入本地登录页面;
      if (this.isLocalDebugMode()) {
        let uiPagesDir = this.isLocalFileMode()
          ? `static${envDir}`
          : "/" + envName + envDir;
        window.location.href =
          curPath.slice(0, curPath.lastIndexOf(uiPagesDir)) +
          `${uiPagesDir}/common/base/login/index.html?reBackurl=${baseUrl}`;
      } else {
        // jar 包和 agcloud 框架下跳转到 /opus-admin-ui/authentication/require
        // 单页面打开，单点接口适配多内外网多ip情况
        const REG = /^([^\/]+:\/\/)[^\/]+/i;
        let opusAdminUi = window[envName].nacos.opusAdminUi;
        if (opusAdminUi) {
          opusAdminUi = opusAdminUi.endsWith("/")
            ? opusAdminUi
            : opusAdminUi + "/";
        }
        opusAdminUi = new RegExp(REG).test(opusAdminUi)
          ? opusAdminUi.replace(REG, "$1" + window.location.host)
          : opusAdminUi;
        window.location.href =
          opusAdminUi + "authentication/require?reBackurl=" + baseUrl;
      }
    }
    return tokenOk;
  }

  //同步读取nacos变量，通过访问配套的controller接口来获取，变量会设置到nacosEnv变量中
  setNacosEnv() {
    if (this.isLocalDebugMode()) return;
    try {
      var xhr = new XMLHttpRequest(); //创建对象
      xhr.open("GET", `/${envName}/getSystemEnv.public`, false); //打开连接，同步
      xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8"); //设置请求头
      xhr.setRequestHeader(
        "Authorization",
        "bearer " + localStorage.getItem("access_token")
      );
      xhr.send(); //发送请求
      //存储结果到指定的全局变量
      let result = JSON.parse(xhr.responseText);
      if (result.success) {
        let env = JSON.parse(result.message);
        const REG = /^([^\/]+:\/\/)[^\/]+/i;
        // 替换为浏览器的ip端口
        for (let key in env) {
          if (key == "server" || key == "local" || typeof env[key] !== "string")
            continue;
          env[key] = new RegExp(REG).test(env[key])
            ? env[key].replace(REG, "$1" + window.location.host)
            : env[key];
        }
        this.nacos = env;
      } else {
        console.error("接口失败，采用默认调试配置");
      }
    } catch (error) {
      //因为本地文件打开或者其他情况访问不了的，就会这样，然后对应的地方拿不到值就用调试的默认值，不要把默认值写在这里！
      console.error("接口错误，采用默认调试配置");
      console.log(this.nacos);
    }
  }

  //为访问的文件增加前缀
  setPrefix(url) {
    if (url.indexOf("esri/css") > -1 || url.indexOf("api/libs/jsapi/") > -1) {
      //访问arcgis的js
      return this.nacos.arcgisApi + url;
    }
    if (url.startsWith("/agcloud/framework")) {
      !this.nacos.opusFrontSso.endsWith("/") &&
        (this.nacos.opusFrontSso = this.nacos.opusFrontSso + "/");
      url.startsWith("/") && (url = url.substring(1));
      //都指向sso，因为sso是必定存在的
      return this.nacos.opusFrontSso + url;
    }
    return url;
  }
}

//*******************************************这里开始执行正式的逻辑
//生成对应的全局变量
window[envName] = new SystemEnv();
//先执行token检查, 再获取nacos变量到其nacosEnv变量对象中
with (window[envName]) if (checkToken()) setNacosEnv();

if (window[envName].isLocalDebugMode()) {
  // 本地调试时去掉 _fetchAccessTokenName 报错;
  var _fetchAccessTokenName = function (bol) {};
}

/**
 * html 加载 CSS 方法;
 * @param {Array} inputUrl CSS 列表;
 * @param {Array} id 每个 CSS 对应ID，两个数组同一位置的数据会互相对应
 */
function loadCSS(inputUrl, id) {
  let headDOM = document.head;
  if (inputUrl instanceof Array) {
    let fragment = document.createDocumentFragment();
    for (let idx = 0; idx < inputUrl.length; idx++) {
      let currentUrl = inputUrl[idx];
      let c = document.createElement("link");
      c.setAttribute("charset", "utf-8");
      c.setAttribute("rel", "stylesheet");
      c.setAttribute("href", window[envName].setPrefix(currentUrl));
      if (id && id[idx]) {
        c.setAttribute("id", id[idx]);
      }
      fragment.appendChild(c);
    }
    headDOM.appendChild(fragment);
  } else {
    console.error("函数 loadCSS 传数组");
  }
}

/**
 * html 加载 JS 方法;
 * @param {Array} urls JS 列表;
 * @param {boolean} sync 是否同步;
 */
function loadJS(urls, sync) {
  let scriptTag;
  if (sync) {
    scriptTag = "script"; //同步加载
  } else {
    scriptTag = "script defer"; //延迟加载
  }
  //用document.write确保顺序
  urls.forEach(function (url) {
    url = window[envName].setPrefix(url);
    document.write("<" + scriptTag + " src=" + url + "></script>");
  });
}

/**
 * 跳转到登录页面, 需要对当前页面 url 编码并添加到登录页面的 url 后面;
 */
function Base64() {
  // private property
  let _keyStr =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

  // public method for encoding
  this.encode = function (input) {
    let output = "",
      chr1,
      chr2,
      chr3,
      enc1,
      enc2,
      enc3,
      enc4,
      i = 0;
    input = _utf8_encode(input);
    while (i < input.length) {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);
      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;
      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }
      output =
        output +
        _keyStr.charAt(enc1) +
        _keyStr.charAt(enc2) +
        _keyStr.charAt(enc3) +
        _keyStr.charAt(enc4);
    }
    return output;
  };

  // private method for UTF-8 encoding
  _utf8_encode = function (string) {
    string = string.replace(/\r\n/g, "\n");
    var utftext = "";
    for (var n = 0; n < string.length; n++) {
      var c = string.charCodeAt(n);
      if (c < 128) {
        utftext += String.fromCharCode(c);
      } else if (c > 127 && c < 2048) {
        utftext += String.fromCharCode((c >> 6) | 192);
        utftext += String.fromCharCode((c & 63) | 128);
      } else {
        utftext += String.fromCharCode((c >> 12) | 224);
        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
        utftext += String.fromCharCode((c & 63) | 128);
      }
    }
    return utftext;
  };
}
